home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / NCSA / tn3270 2.4d7 source / NCSA⁄BYU TCP⁄IP / dlayer.c < prev    next >
Text File  |  1991-06-27  |  11KB  |  420 lines

  1. /*   
  2. *     DLAYER
  3. *     Hardware level routines, data link layer
  4. *
  5. ****************************************************************************
  6. *                                                                          *
  7. *      part of:                                                            *
  8. *      TCP/IP kernel for NCSA Telnet                                       *
  9. *      by Tim Krauskopf                                                    *
  10. *                                                                          *
  11. *      National Center for Supercomputing Applications                     *
  12. *      152 Computing Applications Building                                 *
  13. *      605 E. Springfield Ave.                                             *
  14. *      Champaign, IL  61820                                                *
  15. *                                                                          *
  16. *    Copyright (c) 1987, Board of Trustees of the University of Illinois   *
  17. *                                                                          *
  18. ****************************************************************************
  19. */
  20. #include <stdio.h>
  21. #include <String.h>
  22. #include <Events.h>
  23. #include <AppleTalk.h>
  24.  
  25. #include "protocol.h"
  26. #include "data.h"
  27. #include "mactools.h"
  28. #include "tools.h"
  29. #include "croft.h"
  30.  
  31. /************************************************************************/
  32. /*
  33. *   Address Resolution Protocol handling.  This can be looked at as
  34. *   Ethernet-dependent, but the data structure can handle any ARP
  35. *   hardware, with minor changes here.
  36. *
  37. */
  38. replyarp(thardware,tipnum)
  39.     uint8 *thardware,*tipnum;
  40.     {
  41.     uint8 *pc;
  42.  
  43.     movebytes(&arp.tha,thardware,DADDLEN);   /* who this goes to */
  44.  
  45.     movebytes(&arp.tpa,tipnum,4);        /* requester's IP address */
  46.     arp.op = intswap(ARPREP);            /* byte swapped reply opcode */
  47.  
  48.     movebytes(arp.d.dest,thardware,DADDLEN);    /* hardware place to send to */
  49.  
  50.     dlayersend(&arp,sizeof(arp));
  51.  
  52. /*
  53. *  check for conflicting IP number with your own
  54. */
  55.     if (comparen(tipnum,nnipnum,4))    {     /* we are in trouble */
  56.         pc = neterrstring(-1);
  57.         sprintf(pc,"Conflict with Ethernet hardware address: %2x:%2x:%2x:%2x:%2x:%2x",
  58.         thardware[0],thardware[1],thardware[2],thardware[3],thardware[4],thardware[5]);
  59.         netposterr(-1);
  60.         netposterr(102);
  61.         return(-3);
  62.     }
  63.  
  64. }
  65.  
  66. /*************************************************************************/
  67. /* cacheupdate
  68. *  We just received an ARP, or reply to ARP and need to add the information
  69. *  to the cache.
  70. *
  71. *  Reset arptime so that another machine may be ARPed.  This timer keeps
  72. *  ARPs from going out more than one a second unless we receive a reply.
  73. */
  74. static int32 arptime=0L;
  75.  
  76. int cacheupdate
  77.   (
  78.     uint8 *ipn,
  79.     uint8 *hrdn
  80.   )
  81.     {
  82.     int i,found;
  83.     int32 timer;
  84.  
  85.     found = -1;
  86. /*
  87. * linear search to see if we already have this entry
  88. */
  89.     for (i=0; found < 0 && i < CACHELEN; i++) 
  90.         if (comparen(ipn,&arpc[i].ip,4))
  91.             found = i;
  92.  
  93. /*
  94. *  if that IP number is not already here, take the oldest entry.
  95. *  If it is already here, update the info and reset the timer.
  96. *  These were pre-initialized to 0, so if any are blank, they will be
  97. *  taken first because they are faked to be oldest.
  98. */
  99.     if (found < 0) {
  100.         timer = arpc[0].tm;
  101.         found = 0;
  102.  
  103.         for (i=1; i < CACHELEN; i++) 
  104.             if (arpc[i].tm < timer && !arpc[i].gate) {/* exclude gateways */
  105.                 found = i;
  106.                 timer = arpc[i].tm;
  107.             }
  108.     }
  109. /*
  110. *   do the update to the cache
  111. */
  112.  
  113.     movebytes(&arpc[found].hrd,hrdn,DADDLEN);
  114.     movebytes(&arpc[found].ip,ipn,4);
  115.     arpc[found].tm = time(NULL);
  116.  
  117.     arptime = 0L;                    /* reset, allow more arps */
  118.     return(found);
  119.  
  120. }
  121.  
  122. /************************************************************************/
  123. /*  reqarp
  124. *    put out an ARP request packet, doesn't wait for response
  125. */
  126. int reqarp
  127.   (
  128.     uint8 *tipnum
  129.   )
  130.     {
  131.  
  132. #ifdef MAC
  133.     if (KIP) {
  134.         if (0 < KIParp(tipnum, (AddrBlock *) &arp.tha))
  135.             cacheupdate(tipnum, &arp.tha);
  136.         return(0);
  137.     }
  138. #endif MAC
  139.  
  140.     movebytes(&arp.tha,broadaddr,DADDLEN); 
  141.     movebytes(&arp.tpa,tipnum,4);              /* put in IP address we want */
  142.     arp.op = intswap(ARPREQ);                /* request packet */
  143.  
  144.     movebytes(arp.d.dest,broadaddr,DADDLEN);        /* send to everyone */
  145.  
  146.     if (dlayersend(&arp,sizeof(arp)))
  147.         return(1);                          /* error return */
  148.  
  149.     return(0);
  150. }
  151.  
  152. /************************************************************************/
  153. /*  interpret ARP packets
  154. *   Look at incoming ARP packet and make required assessment of usefulness,
  155. *   check to see if we requested this packet, clear all appropriate flags.
  156. */
  157. int arpinterpret
  158.   (
  159.     ARPKT *p
  160.   )
  161.     {
  162.  
  163. /*
  164. *  check packet's desired IP address translation to see if it wants
  165. *  me to answer.
  166. */
  167.     if (p->op == intswap(ARPREQ) && (comparen(&p->tpa,nnipnum,4))) { 
  168.  
  169.         cacheupdate(&p->spa,&p->sha);   /* keep her address for me */
  170.  
  171.         replyarp(&p->sha,&p->spa);        /* proper reply */
  172.         return(0);
  173.     }
  174. /*
  175. *  Check for a RARP reply.  If present, call netsetip()
  176. */
  177.     else if (p->op == intswap(RARPR) && (comparen(&p->tha,nnmyaddr,DADDLEN))) {
  178.         movebytes(nnipnum,&p->tpa,4);
  179.         return(0);
  180.     }
  181.  
  182. /* 
  183. *  Check for a reply that I probably asked for.
  184. */
  185.     if (comparen(&p->tpa,nnipnum,4)) {
  186.         if (p->op == intswap(ARPREP) &&
  187.             p->hrd == intswap(HTYPE) &&       /* consistency checking */
  188.             p->hln == DADDLEN &&
  189.             p->pln == 4 ) {
  190.             cacheupdate(&p->spa,&p->sha);
  191.             return(0);
  192.         }
  193.     }
  194.  
  195.     return(1);
  196.  
  197. }
  198.  
  199. /*************************************************************************/
  200. /* rarp
  201. *  Send a rarp request to look up my IP number
  202. */
  203. rarp()
  204.     {
  205. /*
  206. *  our other fields should already be loaded
  207. */
  208.     movebytes(&arp.tha,nnmyaddr,DADDLEN);   /* address to look up (me) */
  209.     movebytes(&arp.sha,nnmyaddr,DADDLEN);   /* address to look up (me) */
  210.     arp.op = intswap(RARPQ);                /* request packet */
  211.  
  212.     movebytes(arp.d.dest,broadaddr,DADDLEN);        /* send to everyone */
  213.     arp.d.type = ERARP;
  214.  
  215.     if (dlayersend(&arp,sizeof(arp)))
  216.         return(1);                          /* error return */
  217.  
  218.     arp.d.type = EARP;                        /* set back for ARP to use */
  219.     return(0);
  220.  
  221. }
  222.  
  223. /*************************************************************************/
  224. /*  cachelook
  225. *   look up information in the cache
  226. *   returns the cache entry number for the IP number given.
  227. *   Returns -1 on no valid entry, also if the entry present is too old.
  228. *
  229. *   doarp is a flag for non-gateway requests which determines whether an
  230. *   arp will be sent or not.
  231. */
  232.  
  233. int cachelook
  234.   (
  235.     uint8 *ipn,
  236.     int gate,
  237.     int doarp
  238.   )
  239.     {
  240.     int i,haveg;
  241. /*
  242. *  First option, we are not looking for a gateway, but a host on our
  243. *  local network.
  244. */
  245.     if (!gate) {
  246.         for (i=0; i<CACHELEN; i++)
  247.             if (comparen(ipn,&arpc[i].ip,4) && 
  248.                 arpc[i].tm + CACHETO > time(NULL)) 
  249.                 return(i);
  250. /*
  251. *  no valid entry, send an ARP
  252. */
  253.         if (time(NULL) >= arptime && doarp) {    /* check time limit */
  254.             reqarp(ipn);                /* put out a broadcast request */
  255.             arptime = time(NULL)+ARPTO;
  256.         }
  257.         return(-1);
  258.     }
  259.     else {
  260. /*
  261. *  Second option, we need a gateway.
  262. *  if there is a gateway with a current ARP, use it.
  263. *  if not, arp all of the gateways and return an error.  Next call will
  264. *  probably catch the result of the ARP.
  265. */
  266.         haveg = 0;
  267.         for (i=CACHELEN-1; i >= 0; i--)
  268.             if (arpc[i].gate && arpc[i].tm + CACHETO > time(NULL))
  269.                 return(i);
  270.  
  271.         if (time(NULL) >= arptime) {    
  272.             for (i=CACHELEN-1; i >= 0; i--)
  273.                 if (arpc[i].gate) {
  274.                     haveg = 1;
  275.                     reqarp(&arpc[i].ip);    /* put out a broadcast request */
  276.                 }
  277.  
  278.             if (!haveg)             /* blind luck, try ARPing even for */
  279.                 reqarp(ipn);        /* a node not on our net. (proxy ARP)*/
  280.  
  281.             arptime = time(NULL)+ARPTO;
  282.         }
  283.  
  284.         return(-1);
  285.     }
  286.  
  287. }
  288.  
  289. /***************************************************************************/
  290. /*  netdlayer
  291. *       get data layer address for insertion into outgoing packets.
  292. *   searches based on ip number.  If it finds the address, ok, else . . .
  293. *
  294. *   Checks to see if the address is on the same network.  If it is,
  295. *   then ARPs the machine to get address.  Forces pause between sending
  296. *   arps to guarantee not saturating network.
  297. *
  298. *   If not on the same network, it needs the ether address of a 
  299. *   gateway.  Searches the list of machines for a gateway flag.
  300. *   Returns the first gateway found with an Ethernet address. 
  301. *
  302. *   Returns NULL if not here, or pointer to ether address
  303. *   If we don't have it, this also sends an ARP request so that the
  304. *   next time we are called, the ARP reply may be here by then.
  305. *
  306. */
  307. uint8
  308. *netdlayer(tipnum)
  309.     uint8 *tipnum;
  310.     {
  311.     int32 t;
  312.     uint8 *pc;
  313.  
  314.     t = time(NULL) + nndto*TICKSPERSEC;            /* some seconds time out */
  315.     pc = NULL;
  316.     do {
  317.         if (t <= time(NULL))                     /* timed out */
  318.             return(NULL);
  319.         pc = getdlayer(tipnum);
  320.         netsleep(0);                            /* can't have deadlock */
  321.     } while (pc == NULL);
  322.  
  323.     return(pc);
  324. }
  325.  
  326. /***************************************************************************/
  327. /*  netgetrarp
  328. *   Look for a RARP response to arrive
  329. *   wait for nndto seconds before returning failure.
  330. *   If response arrives, return success.
  331. */
  332. int netgetrarp
  333.   (
  334.     void
  335.   )
  336.   {
  337.     int32 t,tr;
  338.  
  339.     t = time(NULL) + nndto*TICKSPERSEC*3;        /* some seconds time out */
  340.     tr = 0L;                                    /* one second retry */
  341.  
  342.     do {
  343.         if (tr <= time(NULL)) {                    /* need retry? */
  344.             rarp();
  345.             tr = time(NULL) + TICKSPERSEC;
  346.         }
  347.  
  348.         if (t <= time(NULL)) {                    /* timed out */
  349.             netposterr(103);
  350.             return(-1);
  351.         }
  352.  
  353.         netsleep(0);                            /* can't have deadlock */
  354.     } while (comparen(nnipnum,"RARP",4));        /* until RARP is served */
  355.  
  356.     return(0);
  357.   }
  358.  
  359. /***************************************************************************/
  360. /*  getdlayer
  361. *   check for the hardware address one time
  362. */
  363. uint8
  364. *getdlayer(tipnum)
  365.     uint8 *tipnum;
  366.     {
  367.     int needgate,i;
  368.  
  369.     needgate = 0;
  370.  
  371. /*
  372. *  Check to see if we need to go through a gateway.
  373. *  If the machine is on our network, then assume that we can send an ARP
  374. *  to that machine, otherwise, send the ARP to the gateway.
  375. *
  376. *  Uses internet standard subnet mask method, RFC950
  377. *  if subnets are not in use, netmask has been pre-set to the appropriate 
  378. *  network addressing mask.
  379. */ 
  380.     for (i=3; i >= 0; i--)
  381.         if ((nnmask[i] & tipnum[i]) != (nnmask[i] & nnipnum[i]))
  382.             needgate = 1;
  383.  
  384.     if (needgate && (0 <= (i = cachelook(tipnum,1,1)))) 
  385.         return(&arpc[i].hrd);
  386.  
  387.     if (!needgate && (0 <= (i = cachelook(tipnum,0,1))))
  388.         return(&arpc[i].hrd);
  389.  
  390.     return(NULL);
  391. }
  392.  
  393. /***************************************************************************/
  394. /*  netsetgate
  395. *   Establish an IP number to use as a gateway.
  396. *   They are added in the order that they arrive and there is a limit on
  397. *   the number of gateways equal to CACHELEN/2.
  398. *   ARPs them as they are added so that the Cache will get pre-filled
  399. *   with gateways.
  400. *
  401. *   returns 0 if ok, -1 on error (full)
  402. */
  403. int netsetgate
  404.   (
  405.     uint8 *ipn
  406.   )
  407.     {
  408.     int i;
  409.  
  410.     for (i=CACHELEN-1 ; i >= CACHELEN/2 ; i--)
  411.         if (!arpc[i].gate) {
  412.             arpc[i].gate = 1;
  413.             movebytes(&arpc[i].ip,ipn,4);
  414.             reqarp(ipn);
  415.             return(0);
  416.         }
  417.  
  418.     return(-1);
  419. }
  420.